from py2neo import Graph,Node,Relationship,NodeMatcher,RelationshipMatcher
import ast
import json

def connect():
    """
    初始化连接数据库
    """

    uri = ""

    user = ""
    password = ""
    
    graph = Graph(uri,auth=(user,password))

    ##执行一次查询，确定是否成功连接数据库
    result = graph.run("MATCH (p:Person) RETURN p.name")
    for record in result:
        if record["p.name"] =="Alice":
            print("数据库连接成功！\n")
        else:
            print("数据库连接失败！\n")
    return graph

def execute_cypher(cypher_query):
    """
    执行cypher语句
    """
    graph = connect()
    result = graph.run(cypher_query)
    return result

def selectNodeByNodeName(node_name,selectType,selectMode=0):
    """
    搜索:
    mode = 0->精确搜索
    mode =1->模糊搜索
    根据标签和结点名称获取结点
    """
    graph = connect()
    print('mode:',selectMode)
    print('node_name:',node_name)
    print("selectType:",selectType)
    assert selectMode == 0 or selectMode  == 1,'selectMode有误!'
    result = []
    if selectType != "来源植物名":
        if selectMode == 0:
            matcher = NodeMatcher(graph)
            node = matcher.match(selectType,name=node_name).first()
            result.append({'n':node})
        else:
            query = f"MATCH (n:{selectType}) WHERE n.name CONTAINS '{node_name}' RETURN n"
            result = graph.run(query).data()
            print(type(result[0]))
            print(len(result))
            print(result)
    else:
        if selectMode == 0:
            matcher = NodeMatcher(graph)
            node = matcher.match(selectType,中文名=node_name).first()
            result.append({'n':node})
        else:
            query = f"MATCH (n:{selectType}) WHERE n.中文名 CONTAINS '{node_name}' RETURN n"
            result = graph.run(query).data()
    return result

def selectNode(nodeName,selectType):
    """
    根据结点名和类型返回匹配的第一个结点
    """
    graph = connect()
    matcher = NodeMatcher(graph)
    node = matcher.match(selectType,name=nodeName).first()

    return node
def selectNodeByID(nodeID,selectType):
    """
    根据结点ID返回数据库匹配的唯一结点
    """
    graph = connect()
    matcher = NodeMatcher(graph)
    if selectType not in ["疾病","Text","EnText"]:
        print("i am not here!")
        node = matcher.match(selectType,ID=nodeID).first()
    else:
        print("i am here!")
        node = matcher.match(selectType,id=nodeID).first()
    return node
def getPropertyOnNode(node):
    """
    以字典形式返回结点的所有属性
    """
    p_dict = dict(node.items())
    return p_dict

def countNodesByLabel(label):
    """
    返回标签的结点数量
    """
    query = f"MATCH (p:{label}) RETURN count(p) as count"
    return execute_cypher(query).data()[0]['count']

def countRelationsByLabel(label):
    """
    返回label代表的关系数量
    """
    query = f"MATCH () -[r:{label}]->() RETURN COUNT(r)"
    return execute_cypher(query).data()[0]['COUNT(r)']

def getNodesCount(lst):
    """
    返回lst中的所有label所代表的节点数目
    """
    result = []

    for label in lst:
        temp = {}
        temp[label] = countNodesByLabel(label)
        result.append(temp)
    print('nodesCount',result)
    return result

def getRelationsCount(lst):
    """
    返回lst中所有关系的数量
    """
    result = []

    for label in lst:
        temp = {}
        temp[label] = countRelationsByLabel(label)
        result.append(temp)
    print('relationsCount',result)
    return result


    

def getKeysOnNode(node):
    """
    以列表形式返回结点的键
    """
    p_list = list(node.keys())
    return p_list

def getValuesOnNode(node):
    """
    以列表形式返回结点的值
    """
    p_list = list(node.values())
    return p_list

def selectNodesByLabel(label):
    """
    根据结点类型，获取所有的结点
    """
    graph = connect()
    query = f"MATCH (node:{label}) RETURN node"
    result = graph.run(query).data()
    # print(result)
    return result

def searchResultList(result,KeyList):
    print('here is temp area!')
    print('keyList:',KeyList)
    resul = []
    for item in result:
        temp = {}
        for k in KeyList:
            temp[k] = item['n'][k]
        print('tempDict:',temp)
        resul.append(temp)
    return resul

def searchResultTransfer(result,selectType):
    """
    每种类型的结果不同，对搜索后的结果进行转换
    中药材：id,name,pinyin,latin,
    """
    resul = []
    keyList =[]
    if selectType =='中药材':
        keyList = ['ID','name','拼音名称','拉丁名']
        print('keyList:',keyList)
        resul = searchResultList(result,keyList)
        print('中药材：',resul)
    elif selectType == '中药组方':
        keyList = ['ID','name','方剂类型','功能']
        resul = searchResultList(result,keyList)
    elif selectType == '靶点':
        keyList = ['ID','name','可选名称','Uniprot数据库ID']
        resul = searchResultList(result,keyList)
    elif selectType == '化合物':
        keyList =['ID','Pubchem ID','name','Formula']
        resul = searchResultList(result,keyList)
    elif selectType == '来源植物名':
        keyList =['ID','中文名','植物种属','分布区域']
        resul = searchResultList(result,keyList)
    elif selectType == '疾病':
        keyList =['id','name','来源疾病数据库','来源疾病数据库id']
        resul = searchResultList(result,keyList)
    else:
        resul = []
    result = {'nodeList':resul,'selectType':selectType,'keyList':keyList}

    return result

def getText(lang,choice):
    assert lang in ['en','zh']
    if lang == 'en':
        selectType = "EnText"
        nodeID = "entext_0" + choice
    else:
        selectType = "Text"
        nodeID = "text_0" + choice
    node =  selectNodeByID(nodeID,selectType)
    print("node:",node)
    properties =  getPropertyOnNode(node)

    return properties

def evalResponse(res):
    string_data = res.replace('\n', '').replace(' ', '')
    triples = ast.literal_eval(string_data)
    nodes = []
    links = []
    # 遍历三元组数据
    for triple in triples:
        source = triple[0]
        relation = triple[1]
        target = triple[2]
        
        # 检查节点是否已经存在于节点列表中
        if source not in nodes:
            nodes.append(source)
        if target not in nodes:
            nodes.append(target)
        
        # 创建关系对象并添加到关系列表中
        link = {
            'source': source,
            'target': target,
            'relation': relation
        }
        links.append(link)
    
    return nodes,links

def evalResponse_1(res):
    result = json.loads(res)
    return result
    
    
